#include "common.h"
S4B Notify(PSIGNAL psignal,U4B type)
{
   PPROCESS ppro=process;
   while(ppro!=PTR_INVALID && ppro->p_pid!=psignal->dt &&ppro->p_pprocessnext!=process)
   { 
      ppro=ppro->p_pprocessnext;
  //  if((*psignal).dt==FSSERVER)
    //Print("%#0cX %X\n\n",(*psignal).sourcepid,(*psignal).signal);
   }

   if(ppro==PTR_INVALID || ppro->p_pid!=psignal->dt) 
   { return ARTIST_ERROR_IPCDESTINATIONNOTEXIST;}


/*----------------------------------------
  ---The signal should follow the rules:
  ---usr->kernelprocess         NO!!!!!!!!!!!!!!!!!!
  ---interrupt->kernel process  ok
  ---interrupt->usr             ok
  ---kernelprocess->usr         ok
  ---usr<->usr                  ok
-----------------------------------------*/
   if(((ppro->p_idcard)<(WhoRunning->p_idcard)) && ReenterKernel==0)/*from the r3,and destination is up .*/
      return ARTIST_ERROR_SIGNALILLEGALUPWARD;


   if(ReenterKernel>0) 
   {   psignal->sourcepid=INTERRUPT;}
   else
   {   (psignal->sourcepid)=(WhoRunning->p_pid);}

/*-----------------------------------------------------------------*/
   if(ppro->p_state==STATE_BORN || ppro->p_state==STATE_ZOMBIE)
      return ARTIST_ERROR_SIGNALDESTINATIONNOTREADY;
/*-----------------------------------------------------------------*/
if(type==SIGNAL_NOTIFY_REALTIME)
{ 

   if(ppro->p_state==STATE_READY)
   {
       switch(psignal->signal)
       {
         case SIGNAL_ZOMBIE:
         {   ppro->p_state=STATE_ZOMBIE;break;}
         case SIGNAL_READY:
         {   ppro->p_state=STATE_READY;break;}
         case SIGNAL_STOPPED:
         {   ppro->p_state=STATE_STOPPED;break;}
         default:
         {
             
             return ARTIST_ERROR_SIGNALUNKOWNREALSIGNAL;
         }
       }
       return ARTIST_ERROR_OK;
   }

   
   if(ppro->p_state==STATE_STOPPED)
   {
       switch(psignal->signal)
       {
         case SIGNAL_ZOMBIE:
         {   ppro->p_state=STATE_ZOMBIE;break;}
         case SIGNAL_READY:
         {   ppro->p_state=STATE_READY;break;}
         case SIGNAL_STOPPED:
         {   ppro->p_state=STATE_STOPPED;break;}
         default:
         {
             return ARTIST_ERROR_SIGNALUNKOWNREALSIGNAL;
         }
       }
       return ARTIST_ERROR_OK; 
   }
   
   if(ppro->p_state==STATE_WAIT)
   {
      if(psignal->signal==SIGNAL_ZOMBIE)/*OK ,the process is killed.It's going to be cleaned away.*/
      {   ppro->p_state=STATE_ZOMBIE;return ARTIST_ERROR_OK;}
      
      if(ppro->p_waitsource==PID_ANYVALID)
      {
          if(ppro->p_waitsignal==SIGNAL_ANY)
          {
			  ppro->p_signalreturn=psignal->returnvalue;
			  ppro->p_waitsignal  =psignal->signal;
			  ppro->p_waitsource  =psignal->sourcepid;			 
		      ppro->p_state=STATE_READY;
			  return ARTIST_ERROR_OK;
		  } 
          if(ppro->p_waitsignal==psignal->signal)
          {
			  ppro->p_signalreturn=psignal->returnvalue;
			//  ppro->p_waitsignal  =psignal->signal;
			  ppro->p_waitsource  =psignal->sourcepid;
			  ppro->p_state=STATE_READY;
			  return ARTIST_ERROR_OK;
		  }
      }
      if(ppro->p_waitsource==psignal->sourcepid )
      {
          if(ppro->p_waitsignal==SIGNAL_ANY)
          {
			  ppro->p_signalreturn=psignal->returnvalue;
			  ppro->p_waitsignal  =psignal->signal;
			 // ppro->p_waitsource  =psignal->sourcepid;
			  ppro->p_state=STATE_READY;/*Print("\nhere\n");*/
			  return ARTIST_ERROR_OK;
		  }
          if(ppro->p_waitsignal==psignal->signal)
          {
			 ppro->p_signalreturn=psignal->returnvalue;
			// ppro->p_waitsignal  =psignal->signal;
			// ppro->p_waitsource  =psignal->sourcepid;
			 ppro->p_state=STATE_READY;
			 return ARTIST_ERROR_OK;
		  }
      }
    }
   return ARTIST_ERROR_INVALIDREALTIMESIGNAL;
}

if(type==SIGNAL_NOTIFY_DELAYED)
{ 
     if(ppro->p_state==STATE_WAIT)
     {//Print("enter the state:%X\n",ppro->p_state);

         if(ppro->p_waitsource==PID_ANYVALID)
         {
            if(ppro->p_waitsignal==SIGNAL_ANY)
            {
                 ppro->p_signalreturn=psignal->returnvalue;
				 ppro->p_waitsignal  =psignal->signal;
				 ppro->p_waitsource  =psignal->sourcepid;			
				 ppro->p_state=STATE_READY;
				 return ARTIST_ERROR_OK;
		    }
            if(ppro->p_waitsignal==psignal->signal)
            {
                 ppro->p_signalreturn=psignal->returnvalue;			 
				// ppro->p_waitsignal  =psignal->signal;
				 ppro->p_waitsource  =psignal->sourcepid;

				 ppro->p_state=STATE_READY;
				 return ARTIST_ERROR_OK;
			}
         }
         if(ppro->p_waitsource==psignal->sourcepid )
         {  
             if(ppro->p_waitsignal==SIGNAL_ANY)
             {
                  ppro->p_signalreturn=psignal->returnvalue;	  
				  ppro->p_waitsignal  =psignal->signal;
				 // ppro->p_waitsource  =psignal->sourcepid;
				  
				  ppro->p_state=STATE_READY;/*Print("\nhere\n");*/
				  return ARTIST_ERROR_OK;
			 }
             if(ppro->p_waitsignal==psignal->signal)
             {
                ppro->p_signalreturn=psignal->returnvalue;
			//	ppro->p_waitsignal	=psignal->signal;
			//	ppro->p_waitsource	=psignal->sourcepid;				
				ppro->p_state=STATE_READY;/*Print("here the state:%X\n",ppro->p_state)*/;
				return ARTIST_ERROR_OK;
			 }
         }
     }
     if(((ppro->p_signalplace+1)%(ppro->p_signallimit))==(ppro->p_signalget))
     {
        // (ppro->p_signalget)=(ppro->p_signalget+1)%(ppro->p_signallimit); ok,the Notify function 
        //can only change the place pointer.So here we give up placing the signal.
        return ARTIST_ERROR_SIGNALBUFFERFULL;
     }
     
      ppro->p_psignal[ppro->p_signalplace]=*psignal;
      (ppro->p_signalplace)=(ppro->p_signalplace+1)%(ppro->p_signallimit);

      return ARTIST_ERROR_OK;
}
   return ARTIST_ERROR_UNKNOWN;
}
S4B NotifyReal(PSIGNAL psignal)
{
   S4B value;
   SystemCallInterrupt((U4B)SYSCALL_NOTIFYSIGNAL,(U4B)psignal,SIGNAL_NOTIFY_REALTIME,(U4B)&value);
   return value;
}
S4B NotifyWaited(PSIGNAL psignal)
{
   S4B value;
   SystemCallInterrupt((U4B)SYSCALL_NOTIFYSIGNAL,(U4B)psignal,SIGNAL_NOTIFY_DELAYED,(U4B)&value);
   return value;
}
